package com.atguigu.guli.service.sms.service.impl;

import com.atguigu.guli.common.util.utils.FormUtils;
import com.atguigu.guli.common.util.utils.RandomUtils;
import com.atguigu.guli.service.base.consts.ServiceConsts;
import com.atguigu.guli.service.base.exception.GuliException;
import com.atguigu.guli.service.base.result.ResultCodeEnum;
import com.atguigu.guli.service.sms.properties.SmsProperties;
import com.atguigu.guli.service.sms.service.SmsService;
import com.atguigu.guli.service.sms.utils.HttpUtils;
import com.google.gson.Gson;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class SmsServiceImpl implements SmsService {
    @Autowired
    SmsProperties smsProperties;
    @Autowired
    RedisTemplate redisTemplate;
    @Override
    public void sendMsg(String mobile, Integer type) {
        //1.正则验证手机号码格式
        boolean b = FormUtils.isMobile(mobile);
        if (!b){
            //手机号码格式错误
            throw  new GuliException(ResultCodeEnum.LOGIN_PHONE_ERROR,new RuntimeException("手机号码格式错误"));
        }

        //2.判断改手机号码是否一分钟内获取过验证码
        String perminKey = ServiceConsts.MOBILE_COUNT_PERMIN_PREFIX+mobile;
        Boolean hasKey = redisTemplate.hasKey(perminKey);
        if (hasKey){//表示一分钟内已经获取过验证码
            throw  new GuliException(ResultCodeEnum.SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL,new RuntimeException(ResultCodeEnum.SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL.getMessage()));
        }
        //3.判断该手机号码24小时内获取验证码的次数是否超过范围：3
        String perdayKey = ServiceConsts.MOBILE_COUNT_PERDAY_PREFIX+mobile;
        Object countObj = redisTemplate.opsForValue().get(perdayKey);
        int count = 0;
        if (countObj!=null){
            count = Integer.parseInt(countObj.toString());
            if (count>=3){//一个手机号码一天内获取验证码的次数超过3次
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR_COUNT_LIMIT_CONTROL,new RuntimeException(ResultCodeEnum.SMS_SEND_ERROR_COUNT_LIMIT_CONTROL.getMessage()));
            }
        }

        //4.调用第三方接口给手机发送验证码
            //生成验证码
            //发送验证码
            //将验证码存到redis缓存
        //5.更新redis中手机号码获取验证码的频率




        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + smsProperties.getAppcode());
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("mobile", mobile);//输入手机号测试
        String code = RandomUtils.getSixBitRandom();//随机生成6位验证码
        querys.put("param", "**code**:"+code+",**minute**:30");
        querys.put("smsSignId", smsProperties.getSmsSignId());
        querys.put("templateId", type==1?smsProperties.getTemplateId1():smsProperties.getTemplateId2());
        Map<String, String> bodys = new HashMap<String, String>();


        try {
            HttpResponse response = HttpUtils.doPost(smsProperties.getHost(),
                    smsProperties.getPath(),
                    smsProperties.getMethod(), headers, querys, bodys);
//            System.out.println(response.toString());
            //获取response的body
            Map resultMap = new Gson().fromJson(EntityUtils.toString(response.getEntity(), "UTF-8"), Map.class);
            if (!"0".equals(resultMap.get("code"))){
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR,new RuntimeException("验证码发送失败"));
            }
            //将验证码缓存到redis中  30分钟
            redisTemplate.opsForValue().set(ServiceConsts.MOBILE_CODE_PREFIX +mobile,code,30, TimeUnit.MINUTES);
            //设置1分钟内不能重复获取验证码
            redisTemplate.opsForValue().set(perminKey+mobile,mobile,60,TimeUnit.SECONDS);
            //更新今天获取验证码的次数
            //先查询次数
            redisTemplate.opsForValue().increment(perdayKey);// 如果perdayKey在redis中不存在，第一次自增时会基于0自增+1
            if (count==0){//表示第一次获取验证码
                redisTemplate.expire(perdayKey,24,TimeUnit.HOURS);
            }
        } catch (Exception e) {
            throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR,new RuntimeException(e));
        }
    }
}
